using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
using OpenComposite.Base.Collections;
using OpenComposite.Base.Designer;
using OpenComposite.EII.CodeGenerators;
using OpenComposite.Repository.Properties;
using OpenComposite.EII.Repository;
using OpenComposite.EII.Services;

namespace OpenComposite.EII.Designer.SCA
{
	public class WorkflowReferenceSymbol : CollapsableSymbol, IRepositoryItemSymbol
	{
		#region Initialization
		/// <summary>
		/// Initializes a new instance of the WorkflowReferenceSymbol class.
		/// </summary>
		public WorkflowReferenceSymbol()
		{
			init();
		}
		private void init()
		{
			this.BeginUpdate();

			this.Border = BorderType.RoundedRectangle;
			this.BorderColor = Color.Black;
			this.BorderStyle = System.Drawing.Drawing2D.DashStyle.Solid;
			this.BorderWidth = 2;

			this.BackColor = Color.FromArgb(64, Color.LemonChiffon);
			this.BackBrushMode = BackgroundBrushMode.LinearGradient;
			this.BackLinearGradientMode = LinearGradientMode.Vertical;

			//this.Name = "serviceModuleSymbol" + GetCount(typeof(ServiceModuleSymbol));
			this.Text = "Orchestration Composite";

			this.Size = new Size(600, 300);
			this.MinimumSize = new Size(70, 50);

			this.UseCustomCollapseClick = true;
			this.CustomCollapseButtonClick += new EventHandler(WorkflowReferenceSymbol_CustomCollapseButtonClick);

			this.NameTextBox.AutoSize = false;
			this.NameTextBox.Width = this.NameTextBox.Width - 20;

			this.CollapsedSize = new Size(130, 80);
			this.CollapsedBorderColor = Color.Black;
			this.CollapsedBackColor = Color.FromArgb(204, 226, 255);
			this.CollapsedBackColor2 = Color.White;
			this.ExpandedSize = new Size(600, 300);
			this.ExpandedBorderColor = Color.Black;
			this.ExpandedBackColor = Color.FromArgb(64, 121, 137, 251);
			this.ExpandedBackColor2 = Color.FromArgb(64, 121, 137, 251);

			//
			// this.ContextMenuStrip
			//
			this.ContextMenuStrip = new ContextMenuStrip();
			this.ContextMenuStrip.Items.Add("Open Orchestration Composite...", null, new EventHandler(context_Open)).Name = "openworkflow";
			this.ContextMenuStrip.Items.Add(new ToolStripSeparator());
			this.ContextMenuStrip.Items.Add("Remove Orchestration Composite", null, new EventHandler(context_Remove));
			this.ContextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(ContextMenuStrip_Opening);

			//
			// Exposed Capability Symbol
			//
			_exposedCapSymbol = null;

			this.IsCollapsed = true;

			this.EndUpdate();
		}

		#endregion

		#region Public Members

		#region Properties
		public override bool CanSelect
		{
			get { return true; }
		}
		public override bool CanFocused
		{
			get { return true; }
		}
		public override bool CanMove
		{
			get { return true; }
		}
		public override bool CanResize
		{
			get { return true; }
		}
		public override bool IsContainer
		{
			get { return true; }
		}
		public override bool NoClip
		{
			get { return false; }
		}
        public ExposedCapabilitySymbol ExposedCapabilitySymbol
        {
            get { return _exposedCapSymbol; }
        }

		#endregion

		#region Override
		public override object GetDragObject(Point location, MouseButtons button)
		{
			return this;
		}
		public override void DropObject(object obj, Point location, MouseButtons button)
		{
		}
		public override bool IsDropAllowed(object obj, Point location, MouseButtons button)
		{
			return false;
		}
		public override bool IsDropAllowed(Type type, Point location, MouseButtons button)
		{
			return false;
		}

		public override bool CreateRouteEnd(DesignerControl controlStart, out IConnector connector,
			out System.Drawing.Drawing2D.LineCap cap, out System.Drawing.Drawing2D.CustomLineCap customcap,
			out RouteDockDirection dockStart, out RouteDockDirection dockEnd,
			out bool useEndConnectorAsRouteEnd)
		{
			bool ok = base.CreateRouteEnd(controlStart, out connector, out cap, out customcap, out dockStart, out dockEnd, out useEndConnectorAsRouteEnd);

			cap = System.Drawing.Drawing2D.LineCap.Custom;
			GraphicsPath path = new GraphicsPath();
			path.AddEllipse(-2.5f, -2.5f, 5f, 5f);
			customcap = new System.Drawing.Drawing2D.CustomLineCap(path, null);

			return ok;
		}

		public override void ReadXml(System.Xml.XmlReader reader)
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null )
				throw new NullReferenceException("RepositoryService not available.");

			System.ComponentModel.BooleanConverter bc = new System.ComponentModel.BooleanConverter();
			try {
				while ( reader.Read() ) {
					switch ( reader.Name ) {
						case "DesignerControl":
							if ( reader.NodeType == System.Xml.XmlNodeType.EndElement ) {
								return;
							}
							break;
						case "Workflow":
							if ( reader.MoveToAttribute("id") && reader.ReadAttributeValue() )
								this.RepositoryItem = repSvc.GetItem<Repository.Workflow>(int.Parse(reader.Value));
							if ( reader.MoveToAttribute("isMainControl") && reader.ReadAttributeValue() )
								if ( reader.Value == true.ToString() && this.DesignerViewControl != null )
									this.DesignerViewControl.MainControl = this;
							if ( reader.MoveToAttribute("isRef") && reader.ReadAttributeValue() )
								this.IsReference = (bool)bc.ConvertFromString(reader.Value);
							break;
						case "DesignerControls":
							// read child controls
							ReadChildControls(reader);
							break;
						default:
							ReadStandardProperties(reader);
							break;
					}
				}
			} finally {
				_exposedCapSymbol = null;
				foreach ( DesignerControl dc in this.Controls ) {
					if ( dc is ExposedCapabilitySymbol ) {
						_exposedCapSymbol = (ExposedCapabilitySymbol)dc;
						break;
					}
				}
			}
			if ( this.RepositoryItem == null ) {
				this.Remove();
			}
		}
		internal void ReadXmlForDroppedItem(System.Xml.XmlReader reader)
		{
			try {
				while ( reader.Read() ) {
					switch ( reader.Name ) {
						case "DesignerControl":
							if ( reader.NodeType == System.Xml.XmlNodeType.EndElement ) {
								return;
							}
							break;
						case "DesignerControls":
							// read child controls
							ReadChildControls(reader);
							break;
						default:
							ReadStandardProperties(reader);
							break;
					}
				}
			} finally {
				_exposedCapSymbol = null;
				foreach ( DesignerControl dc in this.Controls ) {
					if ( dc is ExposedCapabilitySymbol ) {
						_exposedCapSymbol = (ExposedCapabilitySymbol)dc;
						break;
					}
				}
			}
		}
		public override void WriteXml(System.Xml.XmlWriter writer)
		{
			System.ComponentModel.BooleanConverter bc = new System.ComponentModel.BooleanConverter();
			WriteStandardProperties(writer);

			if ( _workflow != null ) {
				writer.WriteStartElement("Workflow");
				writer.WriteAttributeString("id", _workflow.ID.ToString());
				writer.WriteAttributeString("name", _workflow.Name);
				writer.WriteAttributeString("isMainControl", bc.ConvertToString(false));
				writer.WriteAttributeString("isRef", bc.ConvertToString(this.IsReference));
				writer.WriteEndElement();
			}

			WriteChildControls(writer);
		}

		public override void InitializeNew(IServiceProvider serviceProvider)
		{
			RepositoryService repSvc = (RepositoryService)serviceProvider.GetService(typeof(RepositoryService));
			if ( repSvc == null ) throw new NullReferenceException("RepositoryService not available.");

			base.InitializeNew(serviceProvider);

			IRepositoryChangeService svc = serviceProvider.GetService(typeof(IRepositoryChangeService)) as IRepositoryChangeService;
			if ( svc != null ) {
				svc.RepositoryChanged += new RepositoryChangedEventHandler(svc_RepositoryChanged);
			}
			Verb v = null;
			if ( _workflow != null && _workflow.ExtendedProperties.WorkflowStartCapabilityMethodID > 0 ) {
				v = repSvc.GetItem<Verb>(_workflow.ExtendedProperties.WorkflowStartCapabilityMethodID);
			}
			if ( v != null ) {
				ExposedCapabilitySymbol ecs = new ExposedCapabilitySymbol();
				ecs.Verbs = new BindingListEx<Verb>();
				ecs.Verbs.Add(v);
				ecs.ReadOnly = true;
				AddExposedCapabilitySymbol(ecs);
			}
		}
		public override void InitializeLoaded()
		{
			base.InitializeLoaded();
			IRepositoryChangeService svc = this.GetService(typeof(IRepositoryChangeService)) as IRepositoryChangeService;
			if ( svc != null ) {
				svc.RepositoryChanged += new RepositoryChangedEventHandler(svc_RepositoryChanged);
			}
		}

		public override object GetService(Type serviceType)
		{
			if ( _workflow != null )
				return _workflow.GetService(serviceType);
			else
				return base.GetService(serviceType);
		}

		public override void Paint(PaintEventArgs pe)
		{
			base.Paint(pe);

			Rectangle rc = this.GetPaintBounds();
			//Point pt = this.PointToDesignerView(new Point(rc.X, rc.Bottom - 16));
			Point pt = new Point(rc.X + 5, rc.Bottom - 21);
			pe.Graphics.DrawIcon(Resources.ico_workflow, pt.X, pt.Y);
		}
		#endregion

		#region IRepositoryItemSymbol Members

		public bool SaveHierarchy
		{
			get { return false; }
		}

		private bool _isReference = false;
		public bool IsReference
		{
			get { return _isReference; }
			set { _isReference = value; }
		}

		public bool CanBeMainControl
		{
			get { return true; }
		}

		public OpenComposite.EII.Repository.IRepositoryItem RepositoryItem
		{
			get
			{
				return _workflow;
			}
			set
			{
				if ( value is Repository.Workflow ) {
					_workflow = value as Repository.Workflow;
					doItemChanged();
				} else {
					_workflow = null;
				}
			}
		}

		public void Load(int idRepository, int idDomain)
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null ) throw new NullReferenceException("RepositoryService not available.");
			if ( _workflow != null ) {
				this.Text = _workflow.Name;
				if ( _exposedCapSymbol == null ) {
					Verb v = null;
					if ( _workflow.ExtendedProperties.WorkflowStartCapabilityMethodID > 0 ) {
						v = repSvc.GetItem<Verb>(_workflow.ExtendedProperties.WorkflowStartCapabilityMethodID);
					}
					if ( v != null ) {
						ExposedCapabilitySymbol ecs = new ExposedCapabilitySymbol();
						ecs.Verbs = new BindingListEx<Verb>();
						ecs.Verbs.Add(v);
						ecs.Visible = true;
						AddExposedCapabilitySymbol(ecs);
					}
				}
			}
		}
		public bool Save(int idRepository, int idDomain)
		{
			if ( _workflow == null )
				return false;

			return _workflow.Save();
		}

		public bool Delete(bool bAsk)
		{
			if ( _workflow != null ) {
				return _workflow.Delete(bAsk);
			} else {
				return true;
			}
		}
		#endregion

		#endregion

		#region Protected Members

		#region Methods
		protected void AddExposedCapabilitySymbol(ExposedCapabilitySymbol symbol)
		{
			if ( this.IsCollapsed )
				symbol.Collapse();
			else
				symbol.Expand();

			int x = -( symbol.Width / 2 ) - 5;
			int y = ( this.ClientRectangle.Height / 2 ) - ( symbol.Height / 2 );

			symbol.Anchor = AnchorStyles.Left;
			symbol.Location = new Point(x, y);
			symbol.Removed += new EventHandler(symbol_Removed);
			this.Controls.Add(symbol);
			_exposedCapSymbol = symbol;
		}
		#endregion

		#region Override
		protected override Region GetMouseOverArea()
		{
			Region region = base.GetMouseOverArea();
			if ( _exposedCapSymbol != null ) {
				region.Union(_exposedCapSymbol.GetPaintBounds());
			}
			return region;
		}
		protected override void OnTextChanged(EventArgs e)
		{
			if ( _workflow != null ) {
				_workflow.Name = this.Text;
				this.Name = this.Text;
			}
			base.OnTextChanged(e);
		}

		protected override void OnControlAdded(DesignerControl ctrl)
		{
			if ( this.IsCollapsed && !( ctrl is InterfaceSymbol || ctrl is ReferenceSymbol || ctrl is ExposedCapabilitySymbol ) )
				ctrl.Visible = false;
		}
		protected override void OnVisibleChanged()
		{
            return;
			//this.BeginUpdate();
			//foreach ( DesignerControl dc in this.Controls ) {
			//    if ( !( this.IsCollapsed && this.Visible ) ||
			//          ( dc == this.NameTextBox || dc == this.CollapseButton ||
			//            dc is InterfaceSymbol || dc is ReferenceSymbol ) ) {
			//        dc.Visible = this.Visible;
			//        if ( dc == this.CollapseButton && !this.ShowCollapseButton )
			//            dc.Visible = false;
			//    }
			//}
			//this.EndUpdate();
		}

		protected override void SetNameTextboxBounds(bool isCollapsed)
		{
			Rectangle rclient = this.ClientRectangle;
			if ( isCollapsed ) {
				this.NameTextBox.Bounds = new Rectangle(10, 0, rclient.Width - 10 - 20, (int)( rclient.Height / 2 ));
				this.NameTextBox.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;
			} else {
				this.NameTextBox.Bounds = new Rectangle(0, 0, rclient.Width - 20, 15);
				this.NameTextBox.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
			}
		}

		#endregion

		#endregion

		#region Private Members

		#region Variables
		private Repository.Workflow _workflow;
		private ExposedCapabilitySymbol _exposedCapSymbol;
		#endregion

		#region Methods
		private void doItemChanged()
		{
			if ( _workflow != null ) {
				this.Text = _workflow.Name;

				RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
				if ( repSvc == null ) throw new NullReferenceException("RepositoryService not available.");
				Verb v = null;
				if ( _workflow != null && _workflow.ExtendedProperties.WorkflowStartCapabilityMethodID > 0 ) {
					v = repSvc.GetItem<Verb>(_workflow.ExtendedProperties.WorkflowStartCapabilityMethodID);
				}
				if ( v != null ) {
					ExposedCapabilitySymbol ecs = new ExposedCapabilitySymbol();
					ecs.Verbs = new BindingListEx<Verb>();
					ecs.Verbs.Add(v);
					ecs.Visible = true;
					AddExposedCapabilitySymbol(ecs);
				}
			}
		}

		private void openCompositeOrchestration()
		{
			if ( _workflow != null ) {
				//DesignController dc = this.DesignerViewControl.DesignController as DesignController;
				//if ( dc != null )
				//    dc.OpenDiagram(_workflow);
				IMainController mc = this.GetService(typeof(IMainController)) as IMainController;
				if ( mc != null ) mc.OpenDiagram(_workflow);
			}
		}
		#endregion

		#region Event Handlers
		private void WorkflowReferenceSymbol_CustomCollapseButtonClick(object sender, EventArgs e)
		{
			this.DesignerViewControl.BeginInvoke(new MethodInvoker(openCompositeOrchestration));
		}

		private void ContextMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e)
		{
		}

		private void context_Open(object sender, EventArgs e)
		{
			this.DesignerViewControl.BeginInvoke(new MethodInvoker(openCompositeOrchestration));
		}
		private void context_Remove(object sender, EventArgs e)
		{
			this.Remove();
		}
		private void svc_RepositoryChanged(object sender, RepositoryChangedEventArgs e)
		{
			if ( e.RepositoryItem == (IRepositoryItem)this.RepositoryItem &&
				 ( e.Member.Name.StartsWith("AddRepositoryHierarchy") || e.Member.Name == "Save" ||
				   e.Member.Name == "EndEdit" ) ) {
				this.Load(Global.Status.CurrentRepositoryId, Global.Status.CurrentDomainId);
			}
		}

		private void symbol_Removed(object sender, EventArgs e)
		{
			_exposedCapSymbol = null;
		}
		#endregion

		#endregion

	}
}
